/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package commonlib.domain;

/**
 *
 * @author jorge.daniel.negrete
 */
import java.util.*;

public class IteratorTST<T> implements Cloneable {
  class Stackelement
    {
 	  public Node<T> nodo;
	  public int contbro;
	  public Stackelement()
	  {
		  nodo=null;
		  contbro=0;
	  }
    }
  private Stack<Stackelement> llamadas;
  private int cont;
  private Stackelement posicio;
  public IteratorTST(Node<T> nodo)
  {
		llamadas =new Stack<Stackelement>();
		cont=0;
		llamadas=inorden(llamadas,nodo);
		posicio=new Stackelement();
  }
  public Node<T> nextBro()
  {
	  if (!llamadas.empty())
		  {
		    posicio=llamadas.pop();
	      }
	  else
	  {
		  posicio.nodo=null;
	  }
	  return posicio.nodo;
  }
  public boolean hasNextBro()
  {
	if(posicio.nodo==null)
	{
		if(llamadas.empty())
		{
			return  false;
		}
		else
		{
			return true;
		}
	}
	else
	{
		if(posicio.contbro==0)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
  }
  public Node<T> next()
  {
	  if (posicio.nodo!=null)
	  {
	    if(posicio.nodo.getMiddle()!=null)
           {
	    	cont=0;
            llamadas=inorden(llamadas,posicio.nodo.getMiddle());
           }
	  }
	    posicio=llamadas.pop();
	  return posicio.nodo;
  }
  public int hasNext()
  {
	if((llamadas.empty())&&(posicio.nodo==null))
	{
		return 0;
	}
	if(llamadas.empty())
	{
		if(posicio.nodo.getMiddle()==null)
		{
		  return 0;
		}
		else
		{
			return 1;
		}
	}
	else if(posicio.nodo!=null)
	     {
	    	if(posicio.nodo.getMiddle()==null)
	    	{
		         if(this.hasNextBro())
		         {
			          return 1;
		          }
		         else
		          {
			          return llamadas.peek().nodo.getLevel()-this.posicio.nodo.getLevel();
		           }
		     }
		     else
		     {
			  return 1;
		     }
	      }
	else
	{
		return 1;
	}
  }

public int hasNextBack()
{
	if((llamadas.empty())&&(posicio.nodo==null))
	{
		return 0;
	}
	if(posicio.nodo==null)
	{
		return 0;
	}
	if(posicio.nodo.getLevel()==1)
	{
       return 0;
	}
	else
	{
		if(this.hasNextBro())
		{

           int res=llamadas.size()-posicio.contbro;
           if(res==0)
           {
        	   return 0;
           }
           else
           {
        	   return llamadas.elementAt(res-1).nodo.getLevel()-posicio.nodo.getLevel();
           }
		}
		else
		{
		  	if(llamadas.empty())
		  	{
		  		return 0;
		  	}
		  	else
		  	{
		  		return llamadas.peek().nodo.getLevel()-posicio.nodo.getLevel();
		  	}
		}
	}
}
public Node<T> nextBack()
{
   if(this.hasNextBro())
   {
	   for(int i=0;i<posicio.contbro;i++)
	   {
	     	posicio=llamadas.pop();
	   }
	   posicio=llamadas.pop();
	   return posicio.nodo;
   }
   else
   {
	   posicio=llamadas.pop();
	   return posicio.nodo;
   }
}
private Stack<Stackelement> inorden(Stack<Stackelement> ll,Node<T> tr)
{
	if(tr==null) return ll;
	else
	{
		Stackelement e=new Stackelement();
		ll=inorden(ll,tr.getRight());
		e.nodo=tr;
		e.contbro=cont;
		ll.push(e);
		cont=cont+1;
		ll=inorden(ll,tr.getLeft());
		return ll;
	}
}
public Object clone(){
    Object obj=null;
    try{
        obj=super.clone();
    }catch(CloneNotSupportedException ex){
        System.out.println(" no se puede duplicar");
    }
    return obj;
}
}